#pragma once

#include <iostream>
#include <memory>
#include <string>
#include <mutex>
#include <tuple>
#include <unordered_set>
#include "base/Bytes.h"
#include <sw/redis++/redis++.h>
#include "utils/utils.h"
#include <thread>
#include "base/MessageLoop.h"
#include "base/Define.h"
#include "base/Timer.h"
#include <msgpack.hpp>
#include "Serializer.h"

namespace zeroplus::mq
{
    // 延时任务信息
    struct DelayTaskInfo
    {
        std::string topic;
        std::string message;
        MSGPACK_DEFINE(topic, message);
    };
    // 延时任务信息编解码模块
    struct DelayTaskCodec
    {
        static DelayTaskInfo Decode(const Bytes &bytes)
        {
            DelayTaskInfo obj;
            Serializer::convert(bytes, obj);
            return obj;
        }

        static Bytes Encode(const DelayTaskInfo &obj)
        {
            Bytes bytes;
            Serializer::convert(obj, bytes);
            return bytes;
        }
    };
    // Level 0: 1 second ticks, 60 ticks, 1000ms/tick
    // Level 1: 1 minute ticks, 60 ticks, 60000ms/tick
    // Level 2: 1 hour ticks, 24 ticks, 3600000ms/tick
    class DelayQueue
    {
    private:
        std::shared_ptr<sw::redis::Redis> redis_;
        std::vector<std::pair<uint64_t, uint64_t>> levels_;
        MessageLoop loop_;
        std::shared_ptr<Timer> searchDelayTaskTimer_;
        std::function<bool(const std::string &)> onTaskExecute_; // 回调函数
    public:
        DelayQueue(std::shared_ptr<sw::redis::Redis> redisFd);
        virtual ~DelayQueue();
        // 创建延迟队列
        bool CreateDq(const std::string &key);
        // 写入任务到 Redis
        bool WriteToStorage(const std::string &key, const uint64_t &delay, const Bytes &message);
        // 从 Redis 读取任务
        std::tuple<Bytes, bool> ReadFromStorage(const std::string &key, const int &count = 1, const int &blockSeconds = 0);
        // 获取队列的大小
        long Length(const std::string &key);
        // 检查 key 是否存在
        bool IskeyExists(const std::string &key);
        // 扫描所有 key，并返回所有 stream 类型的 key
        std::vector<std::string> GetAllkey();
        // 启动延迟队列
        void Start();
        // 停止延迟队列
        void Stop();
        // 查找延时任务
        void SearchDelayTask();
        // 标记任务为已删除
        void MarkTaskAsDeleted(const std::string &task);
        // 注册任务执行回调函数
        void RegisterTaskCallback(std::function<bool(const std::string &)> onTaskExecute) { onTaskExecute_ = onTaskExecute; }

    private:
        // 获取分钟级时间片键
        std::string GetMinuteSliceKey(uint64_t timestamp);
        // 过滤已删除的任务
        bool IsTaskDeleted(const std::string &task);
    };
}